﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Cci;
using Microsoft.Cci.MutableCodeModel;

namespace Mutator
{
    class ConditionMutantGenerator : Microsoft.Cci.MutableCodeModel.MethodBodyCodeMutator
    {



        public ConditionMutantGenerator(IMetadataHost host)
            : base(host)
        {

        }
        public ConditionMutantGenerator(IMetadataHost host, ISourceLocationProvider/*?*/ sourceLocationProvider)
            : base(host, sourceLocationProvider)
        {

        }

        public override IExpression Visit(LessThanOrEqual lessThanOrEqual)
        {
            Console.WriteLine("++++++ lessThanOrEqual");
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp1 = new LessThan();
                newOp1.LeftOperand = lessThanOrEqual.LeftOperand;
                newOp1.RightOperand = lessThanOrEqual.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp1);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp2 = new GreaterThan();
                newOp2.LeftOperand = lessThanOrEqual.LeftOperand;
                newOp2.RightOperand = lessThanOrEqual.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp2);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp3 = new GreaterThanOrEqual();
                newOp3.LeftOperand = lessThanOrEqual.LeftOperand;
                newOp3.RightOperand = lessThanOrEqual.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp3);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp4 = new Equality();
                newOp4.LeftOperand = lessThanOrEqual.LeftOperand;
                newOp4.RightOperand = lessThanOrEqual.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp4);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp5 = new NotEquality();
                newOp5.LeftOperand = lessThanOrEqual.LeftOperand;
                newOp5.RightOperand = lessThanOrEqual.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp5);
            }
            return this.Visit((BinaryOperation)lessThanOrEqual);
        }
        public override IExpression Visit(LessThan lessThan)
        {
            Console.WriteLine("++++++ lessThan");
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp1 = new LessThanOrEqual();
                newOp1.LeftOperand = lessThan.LeftOperand;
                newOp1.RightOperand = lessThan.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp1);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp2 = new GreaterThan();
                newOp2.LeftOperand = lessThan.LeftOperand;
                newOp2.RightOperand = lessThan.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp2);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp3 = new GreaterThanOrEqual();
                newOp3.LeftOperand = lessThan.LeftOperand;
                newOp3.RightOperand = lessThan.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp3);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp4 = new Equality();
                newOp4.LeftOperand = lessThan.LeftOperand;
                newOp4.RightOperand = lessThan.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp4);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp5 = new NotEquality();
                newOp5.LeftOperand = lessThan.LeftOperand;
                newOp5.RightOperand = lessThan.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp5);
            }
            return this.Visit((BinaryOperation)lessThan);
        }

        public override IExpression Visit(GreaterThanOrEqual greaterThanOrEqual)
        {
            Console.WriteLine("++++++ greaterThanOrEqual");
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp1 = new LessThan();
                newOp1.LeftOperand = greaterThanOrEqual.LeftOperand;
                newOp1.RightOperand = greaterThanOrEqual.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp1);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp2 = new GreaterThan();
                newOp2.LeftOperand = greaterThanOrEqual.LeftOperand;
                newOp2.RightOperand = greaterThanOrEqual.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp2);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp3 = new LessThanOrEqual();
                newOp3.LeftOperand = greaterThanOrEqual.LeftOperand;
                newOp3.RightOperand = greaterThanOrEqual.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp3);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp4 = new Equality();
                newOp4.LeftOperand = greaterThanOrEqual.LeftOperand;
                newOp4.RightOperand = greaterThanOrEqual.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp4);
            }

            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp5 = new NotEquality();
                newOp5.LeftOperand = greaterThanOrEqual.LeftOperand;
                newOp5.RightOperand = greaterThanOrEqual.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp5);
            }


            return this.Visit((BinaryOperation)greaterThanOrEqual);
        }
        public override IExpression Visit(GreaterThan greaterThan)
        {
            Console.WriteLine("++++++ greaterThan");
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp1 = new LessThan();
                newOp1.LeftOperand = greaterThan.LeftOperand;
                newOp1.RightOperand = greaterThan.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp1);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp2 = new LessThanOrEqual();
                newOp2.LeftOperand = greaterThan.LeftOperand;
                newOp2.RightOperand = greaterThan.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp2);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp3 = new GreaterThanOrEqual();
                newOp3.LeftOperand = greaterThan.LeftOperand;
                newOp3.RightOperand = greaterThan.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp3);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp4 = new Equality();
                newOp4.LeftOperand = greaterThan.LeftOperand;
                newOp4.RightOperand = greaterThan.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp4);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp5 = new NotEquality();
                newOp5.LeftOperand = greaterThan.LeftOperand;
                newOp5.RightOperand = greaterThan.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp5);
            }

            return this.Visit((BinaryOperation)greaterThan);
        }
        public override IExpression Visit(Equality equality)
        {
            Console.WriteLine("++++++ equality");

            INamespaceTypeReference typeRef = equality.LeftOperand.Type as INamespaceTypeReference;
            if (typeRef == null) return this.Visit((BinaryOperation)equality);
            if (typeRef.ToString().Equals(this.host.PlatformType.SystemFloat32.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemFloat64.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt16.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt32.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt64.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt8.ToString()))
            {
                Mutants.mutantNumber++;
                if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
                {
                    Mutants.toVisit.Remove(Mutants.mutantNumber);
                    BinaryOperation newOp1 = new LessThan();
                    newOp1.LeftOperand = equality.LeftOperand;
                    newOp1.RightOperand = equality.RightOperand;
                    Mutants.mutated = true;
                    return this.Visit(newOp1);
                }
                Mutants.mutantNumber++;
                if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
                {
                    Mutants.toVisit.Remove(Mutants.mutantNumber);
                    BinaryOperation newOp2 = new GreaterThan();
                    newOp2.LeftOperand = equality.LeftOperand;
                    newOp2.RightOperand = equality.RightOperand;
                    Mutants.mutated = true;
                    return this.Visit(newOp2);
                }
                Mutants.mutantNumber++;
                if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
                {
                    Mutants.toVisit.Remove(Mutants.mutantNumber);
                    BinaryOperation newOp3 = new GreaterThanOrEqual();
                    newOp3.LeftOperand = equality.LeftOperand;
                    newOp3.RightOperand = equality.RightOperand;
                    Mutants.mutated = true;
                    return this.Visit(newOp3);
                }
                Mutants.mutantNumber++;
                if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
                {
                    Mutants.toVisit.Remove(Mutants.mutantNumber);
                    BinaryOperation newOp4 = new LessThanOrEqual();
                    newOp4.LeftOperand = equality.LeftOperand;
                    newOp4.RightOperand = equality.RightOperand;
                    Mutants.mutated = true;
                    return this.Visit(newOp4);
                }
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp5 = new NotEquality();
                newOp5.LeftOperand = equality.LeftOperand;
                newOp5.RightOperand = equality.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp5);
            }
            return this.Visit((BinaryOperation)equality);
        }

        public override IExpression Visit(NotEquality notEquality)
        {
            Console.WriteLine("++++++ notEquality");
            ITypeReference typeRef = notEquality.LeftOperand.Type as INamespaceTypeReference;
            if (typeRef == null) return this.Visit((BinaryOperation)notEquality);
            if (typeRef.ToString().Equals(this.host.PlatformType.SystemFloat32.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemFloat64.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt16.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt32.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt64.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt8.ToString()))
            {
                Mutants.mutantNumber++;
                if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
                {
                    Mutants.toVisit.Remove(Mutants.mutantNumber);
                    BinaryOperation newOp1 = new LessThan();
                    newOp1.LeftOperand = notEquality.LeftOperand;
                    newOp1.RightOperand = notEquality.RightOperand;
                    Mutants.mutated = true;
                    return this.Visit(newOp1);
                }
                Mutants.mutantNumber++;
                if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
                {
                    Mutants.toVisit.Remove(Mutants.mutantNumber);
                    BinaryOperation newOp2 = new GreaterThan();
                    newOp2.LeftOperand = notEquality.LeftOperand;
                    newOp2.RightOperand = notEquality.RightOperand;
                    Mutants.mutated = true;
                    return this.Visit(newOp2);
                }
                Mutants.mutantNumber++;
                if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
                {
                    Mutants.toVisit.Remove(Mutants.mutantNumber);
                    BinaryOperation newOp3 = new GreaterThanOrEqual();
                    newOp3.LeftOperand = notEquality.LeftOperand;
                    newOp3.RightOperand = notEquality.RightOperand;
                    Mutants.mutated = true;
                    return this.Visit(newOp3);
                }
                Mutants.mutantNumber++;
                if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
                {
                    Mutants.toVisit.Remove(Mutants.mutantNumber);
                    BinaryOperation newOp4 = new LessThanOrEqual();
                    newOp4.LeftOperand = notEquality.LeftOperand;
                    newOp4.RightOperand = notEquality.RightOperand;
                    Mutants.mutated = true;
                    return this.Visit(newOp4);
                }
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                BinaryOperation newOp5 = new Equality();
                newOp5.LeftOperand = notEquality.LeftOperand;
                newOp5.RightOperand = notEquality.RightOperand;
                Mutants.mutated = true;
                return this.Visit(newOp5);
            }

            return this.Visit((BinaryOperation)notEquality);
        }

        public override IExpression Visit(BinaryOperation operation)
        {
            // Console.WriteLine("++++++ condition_binaryoperation");
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                CompileTimeConstant newOp1 = new CompileTimeConstant() { Value = true, Type = this.host.PlatformType.SystemBoolean };
                Mutants.mutated = true;
                return base.Visit(newOp1);
            }
            Mutants.mutantNumber++;
            if (!Mutants.mutated && Mutants.toVisit.Contains(Mutants.mutantNumber))
            {
                Mutants.toVisit.Remove(Mutants.mutantNumber);
                CompileTimeConstant newOp2 = new CompileTimeConstant() { Value = false, Type = this.host.PlatformType.SystemBoolean };
                Mutants.mutated = true;
                return base.Visit(newOp2);
            }

            return base.Visit(operation);
        }

    }
}